from decimal import Decimal

from django_redis import get_redis_connection
from rest_framework import serializers
from .models import OrderInfo,OrderGoods
from goods.models import SKU,Goods
from datetime import datetime



from django.db import transaction


class SaveOrderSerializers(serializers.ModelSerializer):
    """"
    保存订单序列化器
    """

    class Meta:
        model = OrderInfo
        # 序列化返回的数据
        fields = ('order_id', 'address', 'pay_method')
        # read_only_fields 做序列化输出 ，不做反序列化输入
        read_only_fields = ['order_id']
        #  给字段添加额外参数 'address','pay_method' 验证
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }

        }

    def create(self, validated_data):
        # 在这里涉及到4个表的的同时操作
        #  获取当前保存订单需要的数据
        #  订单编号： 和用户有关系
        user = self.context['request'].user
        # user.id + 当前的时间  1 --- 000000001
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        print(order_id)
        print(type(order_id))
        #  获取数据
        address =  validated_data.get('address')
        pay_method = validated_data.get('pay_method')
        # 订单的状态：
        status =  (OrderInfo.ORDER_STATUS_ENUM['UNPAID']) if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else (OrderInfo.ORDER_STATUS_ENUM['UNSEND'])

        # 保存订单信息表
        #  开启事务 核心：
        with transaction.atomic():
            #  设置事务的保存点
            save_point=transaction.savepoint()
            # 开始保存
            try:
                orderInfo = OrderInfo.objects.create(
                    order_id=order_id,
                    user = user,
                    address=address,
                    total_count=0,
                    total_amount =  Decimal('0.00'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=status
                )
                # 从Redis中获取购物车的勾选数据
                redis_conn = get_redis_connection('cart')
                # 'cart_%d' % user.id
                cart_dict_redis =  redis_conn.hgetall('cart_%d' % user.id)
                selected_ids =  redis_conn.smembers('selected_%d' % user.id)
                #  循环获取购物车中的勾选商品信息--sku_id，数量
                for  sku_id_bytes in selected_ids:
                    #  查询一下sku
                    sku = SKU.objects.get(id=sku_id_bytes)

                    buy_count = int(cart_dict_redis[sku_id_bytes])
                    print(buy_count)
                    #  修改一下当前sku 模型对象中的库存和销量
                    #  获取当前的库存销量
                    origin_sales =  sku.sales
                    origin_stock =  sku.stock
                    #  判断库存 是否充足
                    if buy_count > origin_stock:
                        raise serializers.ValidationError('库存不足')
                    new_sales =  origin_sales +buy_count
                    new_stock =  origin_stock - buy_count
                    result =  SKU.objects.filter(stock=origin_stock,id=sku_id_bytes).update(stock=new_stock,sales=new_sales)
                    if result == 0: #  没有修改成功 ：存在 资源抢夺：
                        continue
                    # 修改spu
                    spu = sku.goods
                    spu.sales =  spu.sales +buy_count
                    spu.save()
                    #  订单商品
                    OrderGoods.objects.create(
                        order =  orderInfo,
                        sku =  sku,
                        count = buy_count,
                        price =  sku.price
                    )
                    # 保存一下订单信息中的商品总额
                    orderInfo.total_count  += buy_count
                    orderInfo.total_amount += (sku.price * buy_count )
                    break
                orderInfo.total_amount += orderInfo.freight
                orderInfo.save()
            except  Exception:
                # 进行回滚
                transaction.savepoint_rollback(save_point)
                return serializers.ValidationError('保存失败')

            else:
                transaction.savepoint_commit(save_point)

            #  清除一下购物车中已经付款了的商品
            pl =  redis_conn.pipeline()
            pl.hdel('cart_%d' % user.id,*selected_ids)
            pl.srem('selected_%d' % user.id,*selected_ids)
            pl.execute()
            return orderInfo

